﻿package com.oxylusflash.AccordionMenu
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import com.oxylusflash.AccordionMenu.MenuItem;
	import caurina.transitions.Tweener;
	
	
	public class MainMenu extends Sprite
	{
		public var Mask:Sprite;
		private var xml:XML;
		private var componentWidth:Number;
		private var componentHeight:Number;
		private var mainItemWidth:Number;
		private var mainItemHeight:Number;
		private var mainItemThumbWidth:Number;
		private var mainItemThumbHeight:Number;
		private var subItemThumbWidth:Number;
		private var subItemThumbHeight:Number;
		private var horizontalPadding:Number;
		private var subItemHeight:Number;
		private var maxMainItems:Number;
		private var thumbPadding:Number;
		private var menuItems:Array;
		private var tempMenu:Number;
		private var crtMenu:Number;
		private var flag:Boolean;
		private var subMenuHeights:Array;
		private var menuItemHeights:Array;
		private var menuIsOpen:Array;
		private var menuItemsY:Array;
		private var closeTime:Number;
		private var expandTime:Number;
		private var subMenuMasks:Array;
		private var mouseIn:Boolean;
		private var crtSpeed:Number=0;
		private var menuHolder:Sprite;
		private var maxSpeed:Number = 10;
		private var sMaskHolder:Sprite;
		private var mHolderHeight:Number;
		private var lastY:Number;
		private var maskHeight:Number;
		private var MenuMask:Sprite;
		
		//constructor
		public function MainMenu()
		{
		
			this.visible = false;
			loadXmlFile(stage.loaderInfo.parameters.xmlFile || "data.xml");
			stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
		
		}
		
		private function stageMouseUp(e:MouseEvent):void 
		{
			rollOverHandler(null);
			checkMenuPosition();
		}
		
		//load the xml file
		public function loadXmlFile(path:String):void
		{
			
			var xmlLoader:URLLoader = new URLLoader;
			xmlLoader.addEventListener(Event.COMPLETE, xmlLoader_completeHandler);
			xmlLoader.load(new URLRequest(path));
		}	
		
		//process the XML file
		private function xmlLoader_completeHandler(event:Event):void
		{
			this.visible = true;
			xml = new XML(event.target.data); 
			componentWidth = Number(xml.settings.componentWidth.text());
			componentHeight = Number(xml.settings.componentHeight.text());
			mainItemWidth = Number(xml.settings.mainItemWidth.text());
			mainItemHeight = Number(xml.settings.mainItemHeight.text());
			mainItemThumbWidth = Number(xml.settings.mainItemThumbWidth.text());
			mainItemThumbHeight = Number(xml.settings.mainItemThumbHeight.text());
			subItemHeight = Number(xml.settings.subItemHeight.text());
			horizontalPadding = Number(xml.settings.horizontalPadding.text());
			subItemThumbWidth = Number(xml.settings.subItemThumbWidth.text());
			subItemThumbHeight = Number(xml.settings.subItemThumbHeight.text());
			thumbPadding = Number(xml.settings.thumbPadding.text());
			expandTime = Number(xml.settings.expandTime.text());
			closeTime = Number(xml.settings.closeTime.text());
			maxMainItems = xml.menu.mainItem.length(); 
			resizeMask();
			buildMenu();
			
		
		}
	
		//resize the mask according to component width and height
		private function resizeMask():void
		{
			Mask.width = componentWidth;
			Mask.height = componentHeight;
			//Mask.visible = false;
			this.mask = Mask;
		}
		
		//start building the menu
		private function buildMenu():void
		{
			subMenuHeights = new Array();
			menuItemHeights = new Array();
			lastY= 0;
			menuItems = new Array();
			menuIsOpen = new Array();
			menuItemsY = new Array();
			menuHolder = new Sprite();
			addChild(menuHolder);
			for (var i:int = 0; i < maxMainItems; i++) 
			{
				var mItem:MenuItem = MenuItem(menuHolder.addChild(new MenuItem())); 
				mItem.resize(mainItemWidth, mainItemHeight);
				mItem.setImageAndText(xml.menu.mainItem[i], mainItemThumbWidth, mainItemThumbHeight, thumbPadding, subItemThumbWidth, subItemThumbHeight);
				mItem.addEventListener(MouseEvent.CLICK, menuClick);
				menuItems.push(mItem);
				mItem.y = lastY;
				menuItemsY.push(mItem.y);
				lastY += mItem.height;
				menuItemHeights.push(mItem.height);
			}
			
			for (var j:int = 0; j < maxMainItems; j++) 
			{			
				subMenuHeights.push(menuItems[j].alpha||0);
			}
			
			drawMenuMask();
			this.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler, false, 0, true);
			this.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler, false, 0, true);
			mHolderHeight = lastY;
		
		}
		
		
		//handler for the roll out event
		private function rollOutHandler(event:MouseEvent):void 
		{
			mouseIn = false;
			//checkMenuPosition();
		}
		
		//handler for the roll out event
		private function rollOverHandler(event:MouseEvent):void 
		{
			mouseIn = true;
			stage.addEventListener(MouseEvent.MOUSE_MOVE , moveHandler);
		
		}
		
		private function moveHandler (e:Event):void
		{
			var dist:Number;
			var posy:Number;
			
			dist = componentHeight - mHolderHeight;
			posy = Math.round(mouseY * (dist / componentHeight));
			
			if (posy >=-0 )
			{
				posy = 0;
			}	
			else if(posy<dist)
			{
				posy = dist;
			}
					
			if (mouseIn)
			{
			Tweener.addTween(menuHolder , { y:posy,rounded:true , time:0.3, transition:"easeoutquad" } );
			Tweener.addTween(sMaskHolder , { y:posy,rounded:true , time:0.3, transition:"easeoutquad" } );
			}
			
		}
		
		
		//draw masks for menu&submenus
		private function drawMenuMask():void
		{
			sMaskHolder = new Sprite();
			addChild(sMaskHolder);
			MenuMask = new Sprite;
			MenuMask.graphics.beginFill(0x000000, 0.5);
			MenuMask.graphics.drawRect(0,0, mainItemWidth, lastY);
			MenuMask.graphics.endFill();
			sMaskHolder.addChild(MenuMask);
			sMaskHolder.mouseEnabled = false;
			MenuMask.mouseEnabled = false;
			
			menuHolder.mask = MenuMask;
			maskHeight = MenuMask.height;
				
			
		}
		
		//menu item click handler
		private function menuClick(e:MouseEvent):void 
		{
			
			crtMenu = menuItems.indexOf(e.currentTarget)
			if (xml.menu.mainItem[crtMenu].subMenu.entry.length() != 0)
			{
			if ( tempMenu != crtMenu) 
			{
				
			if (!menuIsOpen[tempMenu])
			{		
				menuItems[crtMenu].showHitState();
				expandMenu(crtMenu);
			}
			
			else
			{		
				
				menuItems[crtMenu].showHitState();
				closeAndExpandAnother(tempMenu)
				
			}
			}
			else
			{
				
				if (menuIsOpen[crtMenu])
				{
					closeMenu(crtMenu);
					menuItems[tempMenu].resetArrow();
				}
				else
				{				
					menuItems[crtMenu].showHitState();
					expandMenu(crtMenu);
				}
			}
			}
			else
			{
				
				closeMenu(tempMenu);
				
				try 
				{
					if (xml.menu.mainItem[tempMenu].subMenu.entry.length() != 0) menuItems[tempMenu].resetArrow();
				}
				catch (er:Error) { }
				
				
			}
			tempMenu = crtMenu;
			
		}

					
		//open menu
		private function expandMenu(index:Number):void
		{
			
			Tweener.addTween(sMaskHolder, { height:lastY+subMenuHeights[index]-menuItemHeights[index],onUpdate:checkMenuPosition, onComplete:setMenuHeight, time: expandTime, transition: "easeoutquad" } );
			
			for (var i:int = index+1; i < maxMainItems; i++) 
			{
				if (!menuIsOpen[i])
				{
					
				Tweener.addTween(menuItems[i], { y:subMenuHeights[index] + menuItemsY[i] - menuItemHeights[index], time: expandTime, transition: "easeoutquad" } );
				}
			
			}
			menuIsOpen[index] = true;	
				
		}
		
		//close menu
		private function closeMenu(index:Number):void
		{
		
			menuIsOpen[index] = false;
			
			Tweener.addTween(sMaskHolder, { height:lastY,onUpdate:checkMenuPositionWhenClosed,  onComplete:setMenuHeight, time: closeTime, transition: "easeoutquad" } );
			if (index >= 0)
			{
			for (var i:int = index+1; i < maxMainItems; i++) 
			{	
				Tweener.addTween(menuItems[i], { y:menuItemsY[i], time: closeTime, transition: "easeoutquad" } );
				
				
			}
			}
			Tweener.addTween(menuHolder , { y:0 , time:0.3, transition:"easeoutquad" } );
			Tweener.addTween(sMaskHolder , { y:0 , time:0.3, transition:"easeoutquad" } );
			
		}
		
		//close menu and expand another one
		private function closeAndExpandAnother(index:Number):void
		{
			menuIsOpen[index] = false;
			menuIsOpen[crtMenu] = true;	
			Tweener.addTween(sMaskHolder, { height:lastY, onComplete:expandMenu, onCompleteParams:[crtMenu], time: closeTime, transition: "easeoutquad" } );
			for (var i:int = index+1; i < maxMainItems; i++) 
			{
				Tweener.addTween(menuItems[i], { y:menuItemsY[i], onUpdate:checkMenuPosition, time: closeTime,  transition: "easeoutquad" } );
				
			}
			
			menuItems[index].resetArrow();
		}
		
		//check the menu position and corrects it if necessary
		private function checkMenuPosition():void
		{
			if (menuHolder.y + lastY + subMenuHeights[crtMenu]<componentHeight)
			{
				var tempY:Number = menuHolder.y;
				var gotoY:Number = componentHeight - (menuHolder.y + lastY + subMenuHeights[crtMenu]) + menuItemHeights[crtMenu];
				Tweener.addTween(menuHolder, { y:tempY + gotoY, time: .3, transition: "easeoutquad" } );
				Tweener.addTween(sMaskHolder, { y:tempY + gotoY, time: .3, transition: "easeoutquad" } );
				
			}
		}
		
		private function checkMenuPositionWhenClosed():void
		{
			
			if (menuHolder.y + lastY < componentHeight)
			{
				Tweener.addTween(menuHolder, { y:0, time: .3, transition: "easeoutquad" } );
				Tweener.addTween(sMaskHolder, { y:0, time: .3, transition: "easeoutquad" } );
				
			}
		}
		

		//set variable mHolderHeight
		private function setMenuHeight():void
		{
			
			maskHeight = sMaskHolder.height;
			if (menuIsOpen[crtMenu])
				{		
				mHolderHeight = lastY + subMenuHeights[crtMenu] - menuItemHeights[crtMenu];
				}
			else
				{
				mHolderHeight = lastY;
				
				}
			moveHandler(null);
		}
	  
		
	}
}